#include "mystdio.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

MYFILE* my_fopen(const char *filename, const char *mode)
{
    // 1、调用系统调用打开文件
    int fd = -1;
    if(strcmp(mode, "r") == 0)
    {
        fd = open(filename, O_RDONLY);
    }
    else if(strcmp(mode, "w") == 0)
    {
        fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, UMASK);
    }
    else if(strcmp(mode, "a") == 0)
    {
        fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, UMASK);
    }
    else if(strcmp(mode, "a+") == 0)
    {
        fd = open(filename, O_RDWR | O_CREAT | O_APPEND, UMASK);
    }
    else{
        //todo
    }
    
    if(fd < 0)
    {
        //fopen失败返回NULL
        return NULL;
    }
    
    // 2、创建MYFILE结构体
    MYFILE* fp = (MYFILE*)malloc(sizeof(MYFILE));
    if(fp == NULL)
    {
        return NULL;
    }

    // 3、初始化MYFILE内数据
    fp->fileno = fd;
    fp->flag = FLUSH_LINE;  //默认行刷新，方便后续测试
    fp->outbuffer[0] = 0;   //缓冲区置空
    fp->curr = 0;           
    fp->cap = SIZE;

    return fp;
}

// 不暴露给外部
static void fflush_core(MYFILE* fp, int force)
{
    if(fp->curr <= 0)
    {
        //缓冲区没有数据，直接return
        return;
    }
    if(force == FORCE)
    {
        write(fp->fileno, fp->outbuffer, fp->curr);
        fp->curr = 0;
    }
    else{

        if(fp->flag == FLUSH_LINE && fp->outbuffer[fp->curr - 1] == '\n')
        {
            //符合行刷新条件，进行行刷新
            write(fp->fileno, fp->outbuffer, fp->curr);
            fp->curr = 0;
        }
        else if(fp->flag == FLUSH_FULL && fp->curr == fp->cap)
        {
            //符合全刷新条件，进行全刷新
            write(fp->fileno, fp->outbuffer, fp->curr);
            fp->curr = 0;
        }
        else{
            // todo
        }
    }
}

int my_fwrite(const char *s, int size, MYFILE* fp)
{
    // 1、将数据从用户缓冲区拷贝到语言缓冲区
    memcpy(fp->outbuffer + fp->curr, s, size);

    // 2、适时调用write，刷新缓冲区
    fp->curr += size;
    fflush_core(fp, NORMAL);

    // 返回写了多少个单位元素
    return size; 
}

void my_fflush(MYFILE* fp)
{
    fflush_core(fp, FORCE);
}

void my_fclose(MYFILE* fp)
{
    if(fp->fileno < 0)
        return;
    my_fflush(fp);
    close(fp->fileno);
    free (fp);
}



